package com.kamistoat.ruoyi.ruoyimodulessystem.service.impl;

import com.kamistoat.ruoyi.ruoyiapisystem.domain.SysDept;
import com.kamistoat.ruoyi.ruoyiapisystem.entity.SysRoleDeptEntity;
import com.kamistoat.ruoyi.ruoyiapisystem.entity.SysUserEntity;
import com.kamistoat.ruoyi.ruoyicommoncore.constant.UserConstants;
import com.kamistoat.ruoyi.ruoyicommoncore.exception.ServiceException;
import com.kamistoat.ruoyi.ruoyicommoncore.utils.StringUtils;
import com.kamistoat.ruoyi.ruoyicommoncore.utils.page.Query;
import com.kamistoat.ruoyi.ruoyicommonsecurity.utils.SecurityUtils;
import com.kamistoat.ruoyi.ruoyimodulessystem.service.SysDeptService;
import com.kamistoat.ruoyi.ruoyimodulessystem.service.SysRoleDeptService;
import com.kamistoat.ruoyi.ruoyimodulessystem.service.SysUserService;
import com.kamistoat.ruoyi.ruoyimodulessystem.dao.SysDeptDao;
import com.kamistoat.ruoyi.ruoyimodulessystem.vo.TreeSelect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kamistoat.ruoyi.ruoyicommoncore.utils.page.PageUtils;
import com.kamistoat.ruoyi.ruoyiapisystem.entity.SysDeptEntity;


@Service("sysDeptService")
public class SysDeptServiceImpl extends ServiceImpl<SysDeptDao, SysDeptEntity> implements SysDeptService {

    @Autowired
    SysRoleDeptService sysRoleDeptService;
    @Autowired
    SysUserService sysUserService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SysDeptEntity> page = this.page(
                new Query<SysDeptEntity>().getPage(params),
                new QueryWrapper<SysDeptEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<SysDeptEntity> selectDeptList(SysDept sysDept) {
        QueryWrapper<SysDeptEntity> queryWrapper = new QueryWrapper<SysDeptEntity>().eq("del_flag", UserConstants.DEPT_NORMAL);
        if (StringUtils.isNotNull(sysDept.getDeptId())) {
            queryWrapper.eq("dept_id", sysDept.getDeptId());
        }
        if (StringUtils.isNotNull(sysDept.getParentId())) {
            queryWrapper.eq("parent_id", sysDept.getParentId());
        }
        if (StringUtils.isNotEmpty(sysDept.getDeptName())) {
            queryWrapper.like("dept_name", "%" + sysDept.getDeptName() + "%");
        }
        if (StringUtils.isNotEmpty(sysDept.getStatus())) {
            queryWrapper.eq("status", sysDept.getStatus());
        }
        // 被DataScope标注，需要携带数据权限参数
        if (StringUtils.isNotEmpty(SecurityUtils.getLoginUser().getAllowedDeptIds())) {
            queryWrapper.in("dept_id", SecurityUtils.getLoginUser().getAllowedDeptIds());
        }
        queryWrapper.orderByAsc("parent_id", "order_num");
        return this.list(queryWrapper);
    }

    @Override
    public SysDeptEntity getDeptUnderScope(Long deptId) {
        List<Long> deptIds = SecurityUtils.getLoginUser().getAllowedDeptIds();
        if (StringUtils.isNotEmpty(deptIds) && deptIds.contains(deptId)) {
            throw new ServiceException("没有权限访问编号为'" + deptId.toString() + "'的部门数据");
        }
        QueryWrapper<SysDeptEntity> queryWrapper = new QueryWrapper<SysDeptEntity>().eq("dept_id", deptId);
        return this.getOne(queryWrapper);
    }

    /**
     * 构建树形结构
     *
     * @param sysDeptList
     */
    @Override
    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> sysDeptList) {
        // 记录传入list中所有的部门Id. 相当于记录其级别
        List<Long> sysDeptIds = new ArrayList<Long>();
        for (SysDept sysDept : sysDeptList) {
            sysDeptIds.add(sysDept.getDeptId());
        }

        List<SysDept> deptTrees = sysDeptList.stream()
                .filter(sysDept -> {
                    // 先过滤。就是找出 sysDeptList中最高级别的那一批 SysDept。
                    // 最高级别的含义是 父亲Id不在当前 sysDeptList 中。
                    return !sysDeptIds.contains(sysDept.getParentId());
                }).map(topSysDept -> {
                    // 对最高级别的 SysDept进行处理，迭代向下找他们的子结点
                    topSysDept.setChildren(findChildren(topSysDept, sysDeptList));
                    return topSysDept;
                }).collect(Collectors.toList());

        // 就很简单了，就是变个类。
        return deptTrees.stream().map(sysDept -> {
            return new TreeSelect(sysDept);
        }).collect(Collectors.toList());
    }

    /**
     * 根据角色Id查询对应的部门Id
     *
     * @param roleId
     */
    @Override
    public List<Long> selectDeptListByRoleId(Long roleId) {
        List<SysRoleDeptEntity> sysRoleDeptEntityList =
                sysRoleDeptService.list(new QueryWrapper<SysRoleDeptEntity>().select("dept_id").eq("role_id", roleId));
        return sysRoleDeptEntityList.stream().map(SysRoleDeptEntity::getDeptId).collect(Collectors.toList());
    }

    /**
     * 检查部门是否已经存在
     *
     * @param sysDept
     */
    @Override
    public boolean checkDeptNameUnique(SysDept sysDept) {
        SysDeptEntity one = this.getOne(new QueryWrapper<SysDeptEntity>().select("dept_name").eq("dept_name", sysDept.getDeptName()));
        // 同时考虑 新增/修改 两种情况
        return StringUtils.isNotNull(one) && StringUtils.isNotEmpty(one.getDeptName()) && !one.getDeptId().equals(sysDept.getDeptId());
    }

    /**
     * 如果父亲dept允许添加子dept，则新增dept
     *
     * @param sysDeptEntity
     */
    @Override
    public boolean addUnderParentStatus(SysDeptEntity sysDeptEntity) {
        SysDeptEntity parentOne =
                this.getOne(new QueryWrapper<SysDeptEntity>().select("dept_name", "status").eq("dept_id", sysDeptEntity.getParentId()));
        if (StringUtils.isNotNull(parentOne) && StringUtils.equals(parentOne.getStatus(), UserConstants.DEPT_DISABLE)) {
            throw new ServiceException(parentOne.getDeptName() + "已停用，不允许新增部门");
        }

        // 设置祖宗链路
        sysDeptEntity.setAncestors(parentOne.getAncestors() + "," + sysDeptEntity.getParentId());
        return this.save(sysDeptEntity);
    }

    /**
     * 检查deptId下是否存在停用 / 未停用的子部门
     */
    @Override
    public int countChildrenDeptById(Long deptId, String deptStatus) {
        Integer count = baseMapper.selectCount(new QueryWrapper<SysDeptEntity>()
                .select("dept_id")
                .eq("parent_id", deptId)
                .eq("status", deptStatus)
                .last("LIMIT 1"));
        return count;
    }

    /**
     * 检查deptId下是否存在停用 / 未停用的用户
     */
    @Override
    public int countDeptExistUser(Long deptId, String userStatus) {
        Integer count = sysUserService.getBaseMapper().selectCount(new QueryWrapper<SysUserEntity>()
                .select("user_id")
                .eq("dept_id", deptId)
                .eq("status", userStatus)
                .last("LIMIT 1"));
        return count;
    }

    /**
     * 将一个部门的 del_flag 更改为已删除状态
     *
     * @param deptId
     */
    @Override
    public boolean deleteDeptById(Long deptId) {
        SysDeptEntity one = this.getOne(new QueryWrapper<SysDeptEntity>().eq("dept_id", deptId));
        one.setDelFlag(UserConstants.DEPT_DELETED);
        return this.updateById(one);
    }

    /**
     * 递归函数，在 buildDeptTreeSelect() 中被调用
     */
    public List<SysDept> findChildren(SysDept sysDeptParent, List<SysDept> sysDeptList) {
        // 同样使用.stream().filter(函数体)对所有分类进行筛选，找到ParentCid==当前分类的id
        List<SysDept> childrenDept = sysDeptList.stream().filter((sysDept) -> {
            return sysDept.getParentId().equals(sysDeptParent.getDeptId());
        }).map((sysDept) -> {
            // 遍历刚刚找到的子分类，然后这里就是执行递归了
            // 将自身作为getChildren的输入变量，再去找自身的子分类
            sysDept.setChildren(findChildren(sysDept, sysDeptList));
            return sysDept;
        }).collect(Collectors.toList());

        return childrenDept;
    }


//    /**
//     * 构建前端所需要树结构. 被 buildDeptTreeSelect() 方法调用
//     *
//     * @param sysDeptList 部门列表
//     * @return 树结构列表
//     */
//    public List<SysDept> buildDeptTree(List<SysDept> sysDeptList) {
//        List<SysDept> returnList = new ArrayList<SysDept>();
//
//        // 记录传入list中所有的部门Id. 相当于记录其级别
//        List<Long> tempList = new ArrayList<Long>();
//        for (SysDept sysDept : sysDeptList) {
//            tempList.add(sysDept.getDeptId());
//        }
//
//        // 对每一个 SysDept 判断其级别
//        for (SysDept sysDept : sysDeptList) {
//            // 无论传入的List中包含哪些部门，这些部门的等级一定存在一个最高级。
//            // 属于该等级的部门sysDept，它的父部门一定不在传入的List中。
//            if (!tempList.contains(sysDept.getParentId())) {
//                // 那么就在传入的List中寻找这个 sysDept 的子部门，填入到 sysDept.child字段中
//                recursionFn(sysDeptList, sysDept);
//                // 然后把这个 sysDept 放入 returnList 中，returnList就是直接存放传入List中最高级别的sysDept
//                returnList.add(sysDept);
//            }
//        }
//
//        if (returnList.isEmpty()) {
//            returnList = sysDeptList;
//        }
//        return returnList;
//    }
//
//
//    /**
//     * 递归列表。在 buildDeptTree() 方法中被调用
//     */
//    private void recursionFn(List<SysDept> list, SysDept sysDept) {
//        // 得到子节点列表
//        List<SysDept> childList = getChildList(list, sysDept);
//        sysDept.setChildren(childList);
//        for (SysDept tChild : childList) {
//            if (hasChild(list, tChild)) {
//                recursionFn(list, tChild);
//            }
//        }
//    }
//
//
//    /**
//     * 得到子节点列表
//     */
//    private List<SysDept> getChildList(List<SysDept> list, SysDept t) {
//        List<SysDept> tlist = new ArrayList<SysDept>();
//        for (SysDept n : list) {
//            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) {
//                tlist.add(n);
//            }
//        }
//        return tlist;
//    }
//
//    /**
//     * 判断是否有子节点
//     */
//    private boolean hasChild(List<SysDept> list, SysDept t) {
//        return getChildList(list, t).size() > 0;
//    }


}